/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.json.gson;

import com.google.gson.Gson;
import net.apexes.commons.lang.Checks;
import net.apexes.commons.net.JsonHttpClient;

import java.lang.reflect.Type;

/**
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 */
public final class GsonHttps {

    private GsonHttps() {}

    public static JsonHttpClient.JsonEncoder createEncoder() {
        return createEncoder(null);
    }

    public static JsonHttpClient.JsonEncoder createEncoder(Gson gson) {
        return new GsonEncoder(gson);
    }

    public static <R> JsonHttpClient.JsonDecoder<R> createDecoder(Type returnType) {
        return createDecoder(null, returnType);
    }

    public static <R> JsonHttpClient.JsonDecoder<R> createDecoder(Gson gson, Type returnType) {
        return new GsonDecoder<>(gson, returnType);
    }

    public static JsonHttpClient.JsonHttpNoticer forNotice(String url) {
        return forNotice(url, createEncoder());
    }

    public static JsonHttpClient.JsonHttpNoticer forNotice(String url, JsonHttpClient.JsonEncoder encoder) {
        return JsonHttpClient.forNotice(url, encoder);
    }

    public static <R> JsonHttpClient<R> forRequest(String url, Type returnType) {
        return forRequest(url, null, returnType);
    }

    public static <R> JsonHttpClient<R> forRequest(String url, Gson gson, Type returnType) {
        JsonHttpClient.JsonEncoder encoder = createEncoder(gson);
        JsonHttpClient.JsonDecoder<R> decoder = createDecoder(gson, returnType);
        return JsonHttpClient.forRequest(url, encoder, decoder);
    }

    public static <R> JsonHttpClient<R> forRequest(String url, JsonHttpClient.JsonDecoder<R> decoder) {
        JsonHttpClient.JsonEncoder encoder = createEncoder();
        return JsonHttpClient.forRequest(url, encoder, decoder);
    }

    /**
     *
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     */
    private static class GsonEncoder implements JsonHttpClient.JsonEncoder {

        private final Gson gson;

        GsonEncoder(Gson gson) {
            this.gson = gson != null ? gson : new Gson();
        }

        @Override
        public String toJson(Object object) throws Exception {
            if (object == null) {
                return null;
            }
            return gson.toJson(object);
        }

    }

    /**
     *
     * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
     *
     * @param <R>
     */
    private static class GsonDecoder<R> implements JsonHttpClient.JsonDecoder<R> {

        private final Gson gson;
        private final Type returnType;

        GsonDecoder(Gson gson, Type returnType) {
            Checks.verifyNotNull(returnType, "returnType");
            this.gson = gson != null ? gson : Gsons.createGson();
            this.returnType = returnType;
        }

        @Override
        public R fromJson(String json) throws Exception {
            if (Checks.isBlank(json)) {
                return null;
            }
            return gson.fromJson(json, returnType);
        }
    }

}
